from flask_security import login_required, current_user
from copy import copy
from mongoengine import Q
from exlib.flask_restplus.reqparse import RequestParser
from exlib.webbase.response import JsonResponse, SuccessResponse, FailedResponse, TableResponse
from utils.perm import perm_required
from utils import get_pagination_arguments, get_object_or_404
from utils.decorators import marshal_item, marshal_table
from utils.exception import HttpErrException
from app import api_base as api
from exlib.flask_restplus.resource import SingleResource, ListResource, ActionResource
from ..models import User, Role
from ..serializers.user import UserSerializer


class UserView(SingleResource):
    model_class = User
    model_serializer = UserSerializer
    @login_required
    @perm_required('user.base', 'view')
    @api.doc(description="获取用户")
    @marshal_item(UserSerializer)
    def get(self, user_id):
        return get_object_or_404(User, User.id == user_id)

    # def put(self, user_id):
    #     data = request.get_json(force=True, silent=True)
    #     user = UserSerializer(data=data).object
    #     user.id = user_id
    #     user.save()
    #     return SuccessResponse(message='修改用户成功', data=UserSerializer(user).data)


class UserPasswordChangeView(ActionResource):
    poster = RequestParser()
    poster.add_argument('password', type=str, required=True, help='密码')

    @login_required
    @perm_required('user.password', 'edit')
    @api.doc(description="修改用户密码")
    @api.expect(poster)
    def put(self, user_id):
        password = self.poster.parse_args()['password']
        user = User.get_or_none(id=user_id)
        user.reset_password(password)
        user.save()
        # LogEntry.log('修改用户密码', current_user, user)
        return SuccessResponse(message='修改用户密码成功', data=UserSerializer(user).data)


class UserPasswordResetView(ActionResource):
    @login_required
    @perm_required('user.password', 'edit')
    @api.doc(description="重置用户密码")
    def post(self, user_id):
        user = get_object_or_404(User, User.id == user_id)
        user.reset_password()
        user.save()
        # LogEntry.log('重置用户密码', current_user, user)
        return SuccessResponse(message='重置用户密码成功', data=UserSerializer(user).data)


class UserInfoChangeView(ActionResource):
    # method_decorators = [check_basic_permission]
    poster = RequestParser()
    poster.add_argument('name', type=str, store_missing=False, help='用户名')
    poster.add_argument('email', type=str, store_missing=False, help='必须填写email')
    # poster.add_argument('type', type=int, store_missing=False, help='type')
    # poster.add_argument('active', type=int, store_missing=False, help='active')
    poster.add_argument('is_admin', type=int, store_missing=False, help='is_admin')
    poster.add_argument('roles', type=list, location='json', help='角色id列表')

    @api.expect(poster)
    @perm_required('user.base', 'edit')
    @api.doc(description="修改用户信息")
    def put(self, user_id):
        """
            @roles_accepted('admin')
        :param user_id:
        :return:
        """
        oriuser = get_object_or_404(User, User.id == user_id)
        data = self.poster.parse_args()
        args = copy(data)
        roles = data.pop('roles')
        if data:
            oriuser.__data__.update(**data)
            User.edit_unique_check(oriuser)
            oriuser.save()
        if roles is not None:
            oriuser.set_roles(roles)
        # LogEntry.log('修改用户', current_user, oriuser, args)
        return SuccessResponse(message='修改用户信息成功', data=UserSerializer(oriuser).data)


class UsersView(ListResource):
    model_class = User
    model_serializer = UserSerializer

    filter = RequestParser()
    filter.add_argument('name', type=str, oper='contains', store_missing=False, help='用户名<模糊>')
    filter.add_argument('email', type=str, store_missing=False, help='email<模糊>')  # todo@hy
    filter.add_argument('type', type=int, store_missing=False, help='type')
    # filter.add_argument('active', type=bool, store_missing=False, help='active')
    filter.add_argument('role', type=str, required=False, store_missing=False, help='角色，支持,分隔')
    # filter.add_argument('case', type=str, choices=()
    pagination = get_pagination_arguments(order_fields=('order_fields', '-is_xxx,-update_time'))

    @perm_required('user.list', 'view')
    @api.expect(pagination, filter)
    @marshal_table(UserSerializer)
    def get(self):
        return self._get()

    def _get(self):
        args = self.filter.parse_args()
        case = args.pop('case', None)
        role = args.pop('role', None)
        roles = role.split(',') if role else None
        conditions = self.filter.get_mge_conditions(User, args)
        if roles:
            conditions['_roles__in'] = roles
        objs = User.objects.filter(**conditions)
        pagination = self.__class__.pagination
        pargs = pagination.parse_args()
        # if case == 'dealmemo_appointment_xxx':
        #     res = self.get_dealmemo_appointment_xxx(deal_id, objs, pargs)
        # elif case == 'evaluation_ration':
        #     res = self.get_evaluation_ration(objs, pargs)
        res = self.order_paginate(objs, pargs)
        return UserSerializer(res).table()

    poster = RequestParser()
    poster.add_argument('name', type=str, location="json", required=True, help='必须填写用户名')
    poster.add_argument('email', type=str, location="json", required=True, help='必须填写email')
    poster.add_argument('phone', type=str, location="json", help='手机号')
    # poster.add_argument('type', type=int, default=0, help='type')
    # poster.add_argument('active', type=bool, default=True, help='active')
    # poster.add_argument('is_admin', type=int, default=0, help='is_admin')
    poster.add_argument('roles', type=list, location='json', store_missing=False, help='角色key列表')

    @login_required
    @api.expect(poster)
    @api.doc(description="新增用户")
    @perm_required('user.base', 'add')
    @marshal_item(UserSerializer)
    def post(self):
        data = self.poster.parse_args()
        if User.objects(email=data['email']).first() or User.objects(name=data['name']).first():
            raise HttpErrException("用户名或者邮箱重复")
        user = User.create_with(data)
        user.save()
        roles = data.pop('roles', None)
        user.reset_password()
        user.save()
        if roles is not None:
            user.set_roles(roles)
        # LogEntry.log('新增用户', current_user, user, "角色:%s" % (roles if roles else ''))
        return UserSerializer(user).item(
            message=self.msg_add_success
        )
